﻿using System.Diagnostics;

namespace DimensionsHelper.LanguageService.Syntax;

public class FunctionDeclaration : DeclarationWithParameters<VariableDeclaration>
{
    private Block _body;

    internal FunctionDeclaration(SyntaxToken declareKeywordToken, Identifier name, SyntaxNode? parent) :
        base(SyntaxKinds.FunctionDeclaration, declareKeywordToken, name, parent)
    {
        _body = Block.Default;
    }


    /// <summary>
    ///     函数体
    /// </summary>
    public Block Body => _body;


    /// <summary>
    ///     如果函数带有返回值，返回true。
    /// </summary>
    public bool HasReturn => DeclareKeywordToken.IsNode(SyntaxKinds.FunctionKeywordToken);


    /// <summary>
    ///     如果当前函数声明节点在无效的上下文中，返回<see langword="true"/>。
    /// </summary>
    public bool InvalidContext =>
        ContainingWithStatement != null || 
        FindParent(parent => parent.IsOneOfNode(
            SyntaxKinds.IfStatement,
            SyntaxKinds.ForStatement,
            SyntaxKinds.ForEachStatement,
            SyntaxKinds.WhileStatement,
            SyntaxKinds.DoStatement,
            SyntaxKinds.SelectStatement,
            SyntaxKinds.FunctionDeclaration)) != null;


    public void Update(Block block)
    {
        SetChildField(ref _body, Block.IsEmptyOrDefault, block);
    }


    public override void AcceptVisitor<T>(SyntaxNodeVisitor<T> visitor)
    {
        base.AcceptVisitor(visitor);
        AcceptList(visitor, Parameters);
        Accept(visitor, Body);
    }
}


public static partial class NodeFactory
{
    public static FunctionDeclaration CreateFunctionDeclaration(SyntaxNode? parent, SyntaxToken declareKeywordToken,
        Identifier identifierName, Block? body)
    {
        Debug.Assert(declareKeywordToken.IsOneOfNode(SyntaxKinds.SubKeywordToken,
            SyntaxKinds.FunctionKeywordToken));
        FunctionDeclaration func = new(declareKeywordToken, identifierName, parent);

        if (body != null)
        {
            func.Update(body);
        }

        return func;
    }
}